package comp6231.project.replica.dimitri;
/**
 * Distributed Retail System
 * Oct 8, 2012 
 */


import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @author dimitri.tiago
 *
 */
public class CustomerDatabaseUpdate implements Runnable
{
	private Semaphore writerSemaphore;
	private RandomAccessCustomerRecord updateRecord;
	private String filename;

	public CustomerDatabaseUpdate(Semaphore writerSemaphore, RandomAccessCustomerRecord updateRecord, String filename)
	{
		this.writerSemaphore = writerSemaphore;
		this.updateRecord    = updateRecord;
		this.filename	     = filename;
	}

	@Override
	public void run()
	{
		//TODO:remove test code
		System.out.printf("%s %s\n", Thread.currentThread().getName(), "Entering database update CS");
		
		writerSemaphore.Wait(); // obtain semaphore, entering critical section
								// to ensure atomic update
		try
		{	    
			// determine if record exists in database
			RandomAccessCustomerRecord selectedRecord = selectRecord(updateRecord);
			if ( ! (selectedRecord.getCustomerID().equalsIgnoreCase("")) )
			{
				// find record start position
				long startPosition = findRecStartPosition(selectedRecord.getCustomerID(), selectedRecord.getItemID());

				// update record in database
				RandomAccessFile file = new RandomAccessFile(filename, "rw");

				file.seek(startPosition);
				RandomAccessCustomerRecord newRecord = updateRecord;
				int update 			     = selectedRecord.getNumberOfItems() - newRecord.getNumberOfItems();
				newRecord.setNumberOfItems(update);
				newRecord.write(file);

				//TODO: remove or change message to user.
				//test
				newRecord = selectRecord(updateRecord);

				System.out.printf(
						"Updated record (%s, %d, %d) in datatabasee with (%s %d %d).\n", 
						selectedRecord.getCustomerID(), selectedRecord.getItemID(), selectedRecord.getNumberOfItems(), 
						newRecord.getCustomerID(), newRecord.getItemID(), newRecord.getNumberOfItems());
				
				file.close(); // close file
			}
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}

		writerSemaphore.Signal(); 	// release semaphore, exiting critical section
									// allowing next thread to update
		
		//TODO:remove test code
		System.out.printf("%s %s\n", Thread.currentThread().getName(), "Leaving database update CS");
	}

	private RandomAccessCustomerRecord selectRecord(RandomAccessCustomerRecord selectRecord)
	{
		RandomAccessCustomerRecord record = new RandomAccessCustomerRecord();

		try
		{
			RandomAccessFile file = new RandomAccessFile(filename, "r");
			String customerID	  = selectRecord.getCustomerID();
			int itemID		  = selectRecord.getItemID();

			while ( ! ((record.getCustomerID().equalsIgnoreCase(customerID)) && (record.getItemID() == itemID)) )
			{
				record.read(file);
			}
			
			file.close(); // close file
		} 
		catch (EOFException eofe )
		{
			// record not found. return empty record
			record = new RandomAccessCustomerRecord();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		return record;
	}

	private long findRecStartPosition(String customerID, int itemID)
	{
		long recordStartPosition = 0;

		RandomAccessCustomerRecord record = new RandomAccessCustomerRecord();

		try
		{
			RandomAccessFile file = new RandomAccessFile(filename, "r");

			while ( ! ((record.getCustomerID().equalsIgnoreCase(customerID)) && (record.getItemID() == itemID)) )
			{
				record.read(file);
				recordStartPosition += 20; // count number of records read
			}

			file.close(); // close file
			
			recordStartPosition -= 20; // move to start of record.
		} 
		catch (EOFException eofe )
		{
			// record not found.
			recordStartPosition = -1;
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		return recordStartPosition;
	}

}